package com.bt.framework.decoration

import android.R
import android.content.Context
import android.graphics.Canvas
import android.graphics.Rect
import android.graphics.drawable.Drawable
import android.util.Log
import android.view.View
import androidx.core.graphics.withSave
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.ItemDecoration
import kotlin.math.roundToInt

/**
 * DividerItemDecoration is a [RecyclerView.ItemDecoration] that can be used as a divider
 * between items of a [LinearLayoutManager]. It supports both [.HORIZONTAL] and
 * [.VERTICAL] orientations.
 *
 * <pre>
 * mDividerItemDecoration = new DividerItemDecoration(recyclerView.getContext(),
 * mLayoutManager.getOrientation());
 * recyclerView.addItemDecoration(mDividerItemDecoration);
</pre> *
 */
class SumDividerItemDecoration(context: Context, orientation: Int) : ItemDecoration() {

    companion object {
        const val HORIZONTAL = LinearLayoutManager.HORIZONTAL
        const val VERTICAL = LinearLayoutManager.VERTICAL
        private const val TAG = "DividerItem"
        private val ATTRS = intArrayOf(R.attr.listDivider)
    }

    var drawable: Drawable?
        private set
    private var mDrawLastPositionDivider = true

    private var mOrientation = 0
    private val mBounds = Rect()

    init {
        context.obtainStyledAttributes(ATTRS).run {
            drawable = getDrawable(0)
            if (drawable == null) {
                Log.w(
                    TAG, "@android:attr/listDivider was not set in the theme used for this "
                            + "DividerItemDecoration. Please set that attribute all call setDrawable()"
                )
            }
            recycle()
        }
        setOrientation(orientation)
    }

    /**
     * Sets the orientation of the decoration. This decides if items are laid
     * out from beginning to end start to end or from top to bottom.
     *
     * @param orientation - One of [.HORIZONTAL] or [.VERTICAL]
     */
    fun setOrientation(orientation: Int) {
        require(!(orientation != HORIZONTAL && orientation != VERTICAL))
        this.mOrientation = orientation
    }

    /**
     * Sets the Drawable to use for the divider line.
     *
     * @param drawable Drawable that will draw the divider line
     */
    fun setDrawable(drawable: Drawable) {
        requireNotNull(drawable) { "Drawable can not be null" }
        this.drawable = drawable
    }

    /**
     * 设置是否绘制最后一个item的分割线
     */
    fun isDrawLastPositionDivider(isDraw: Boolean) {
        this.mDrawLastPositionDivider = isDraw
    }

    /**
     * 设置分割线方向
     */
    override fun getItemOffsets(
        outRect: Rect,
        view: View,
        parent: RecyclerView,
        state: RecyclerView.State
    ) {
        if (drawable == null) {
            outRect[0, 0, 0] = 0
            return
        }

        if (mOrientation == VERTICAL) {
            outRect[0, 0, 0] = drawable!!.intrinsicHeight
        } else {
            outRect[0, 0, drawable!!.intrinsicWidth] = 0
        }
    }

    /**
     * 绘制分割线
     */
    override fun onDraw(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {
        if (parent.layoutManager == null || drawable == null) {
            return
        }
        if (mOrientation == VERTICAL) {
            drawVertical(c, parent, state)
        } else {
            drawHorizontal(c, parent, state)
        }
    }

    /**
     * 绘制垂直方向的分割线
     */
    private fun drawVertical(canvas: Canvas, parent: RecyclerView, state: RecyclerView.State) {
        canvas.withSave() {
            var left: Int
            val right: Int
            if (parent.clipToPadding) {
                left = parent.paddingLeft
                right = parent.width - parent.paddingRight
                clipRect(
                    left, parent.paddingTop, right,
                    parent.height - parent.paddingBottom
                )
            } else {
                left = 0
                right = parent.width
            }
            val childCount = parent.childCount
            val lastPosition = state.itemCount - 1
            for (i in 0 until childCount) {
                val child = parent.getChildAt(i)
                val childRealPosition = parent.getChildAdapterPosition(child)
                if (mDrawLastPositionDivider || childRealPosition < lastPosition) {
                    parent.getDecoratedBoundsWithMargins(child, mBounds)
                    val bottom = mBounds.bottom + child.translationY.roundToInt()
                    val top = bottom - drawable!!.intrinsicHeight
                    drawable!!.setBounds(left, top, right, bottom)
                    drawable!!.draw(this)
                }
            }
        }
    }

    /**
     * 绘制水平方向的分割线
     */
    private fun drawHorizontal(canvas: Canvas, parent: RecyclerView, state: RecyclerView.State) {
        canvas.withSave {
            val top: Int
            val bottom: Int
            if (parent.clipToPadding) {
                top = parent.paddingTop
                bottom = parent.height - parent.paddingBottom
                canvas.clipRect(parent.paddingLeft, top, parent.width - parent.paddingRight, bottom)
            } else {
                top = 0
                bottom = parent.height
            }
            val childCount = parent.childCount
            val lastPosition = state.itemCount - 1
            for (i in 0 until childCount) {
                val child = parent.getChildAt(i)
                val childRealPosition = parent.getChildAdapterPosition(child)
                if (mDrawLastPositionDivider || childRealPosition < lastPosition) {
                    parent.layoutManager!!.getDecoratedBoundsWithMargins(child, mBounds)
                    val right = mBounds.right + child.translationX.roundToInt()
                    val left = right - drawable!!.intrinsicWidth
                    drawable!!.setBounds(left, top, right, bottom)
                    drawable!!.draw(this)
                }
            }
            canvas.restore()
        }
    }

}